;with gratitude to
;http://www.paulbourke.net/geometry/polygonise/

(import "./matrix.inc")

;module
(env-push)

(enums +gridcell 0
	(enum p0 p1 p2 p3 p4 p5 p6 p7)
	(enum v0 v1 v2 v3 v4 v5 v6 v7))

(defmacro Gridcell (p0 p1 p2 p3 p4 p5 p6 p7 v0 v1 v2 v3 v4 v5 v6 v7)
	`(list ,p0 ,p1 ,p2 ,p3 ,p4 ,p5 ,p6 ,p7 ,v0 ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7))

(defq +edge_table ''(
		0x0   0x109 0x203 0x30a 0x406 0x50f 0x605 0x70c
		0x80c 0x905 0xa0f 0xb06 0xc0a 0xd03 0xe09 0xf00
		0x190 0x99  0x393 0x29a 0x596 0x49f 0x795 0x69c
		0x99c 0x895 0xb9f 0xa96 0xd9a 0xc93 0xf99 0xe90
		0x230 0x339 0x33  0x13a 0x636 0x73f 0x435 0x53c
		0xa3c 0xb35 0x83f 0x936 0xe3a 0xf33 0xc39 0xd30
		0x3a0 0x2a9 0x1a3 0xaa  0x7a6 0x6af 0x5a5 0x4ac
		0xbac 0xaa5 0x9af 0x8a6 0xfaa 0xea3 0xda9 0xca0
		0x460 0x569 0x663 0x76a 0x66  0x16f 0x265 0x36c
		0xc6c 0xd65 0xe6f 0xf66 0x86a 0x963 0xa69 0xb60
		0x5f0 0x4f9 0x7f3 0x6fa 0x1f6 0xff  0x3f5 0x2fc
		0xdfc 0xcf5 0xfff 0xef6 0x9fa 0x8f3 0xbf9 0xaf0
		0x650 0x759 0x453 0x55a 0x256 0x35f 0x55  0x15c
		0xe5c 0xf55 0xc5f 0xd56 0xa5a 0xb53 0x859 0x950
		0x7c0 0x6c9 0x5c3 0x4ca 0x3c6 0x2cf 0x1c5 0xcc
		0xfcc 0xec5 0xdcf 0xcc6 0xbca 0xac3 0x9c9 0x8c0
		0x8c0 0x9c9 0xac3 0xbca 0xcc6 0xdcf 0xec5 0xfcc
		0xcc  0x1c5 0x2cf 0x3c6 0x4ca 0x5c3 0x6c9 0x7c0
		0x950 0x859 0xb53 0xa5a 0xd56 0xc5f 0xf55 0xe5c
		0x15c 0x55  0x35f 0x256 0x55a 0x453 0x759 0x650
		0xaf0 0xbf9 0x8f3 0x9fa 0xef6 0xfff 0xcf5 0xdfc
		0x2fc 0x3f5 0xff  0x1f6 0x6fa 0x7f3 0x4f9 0x5f0
		0xb60 0xa69 0x963 0x86a 0xf66 0xe6f 0xd65 0xc6c
		0x36c 0x265 0x16f 0x66  0x76a 0x663 0x569 0x460
		0xca0 0xda9 0xea3 0xfaa 0x8a6 0x9af 0xaa5 0xbac
		0x4ac 0x5a5 0x6af 0x7a6 0xaa  0x1a3 0x2a9 0x3a0
		0xd30 0xc39 0xf33 0xe3a 0x936 0x83f 0xb35 0xa3c
		0x53c 0x435 0x73f 0x636 0x13a 0x33  0x339 0x230
		0xe90 0xf99 0xc93 0xd9a 0xa96 0xb9f 0x895 0x99c
		0x69c 0x795 0x49f 0x596 0x29a 0x393 0x99  0x190
		0xf00 0xe09 0xd03 0xc0a 0xb06 0xa0f 0x905 0x80c
		0x70c 0x605 0x50f 0x406 0x30a 0x203 0x109 0x0)
	+tri_table ''(
		(())
		((0 8 3))
		((0 1 9))
		((1 8 3) (9 8 1))
		((1 2 10))
		((0 8 3) (1 2 10))
		((9 2 10) (0 2 9))
		((2 8 3) (2 10 8) (10 9 8))
		((3 11 2))
		((0 11 2) (8 11 0))
		((1 9 0) (2 3 11))
		((1 11 2) (1 9 11) (9 8 11))
		((3 10 1) (11 10 3))
		((0 10 1) (0 8 10) (8 11 10))
		((3 9 0) (3 11 9) (11 10 9))
		((9 8 10) (10 8 11))
		((4 7 8))
		((4 3 0) (7 3 4))
		((0 1 9) (8 4 7))
		((4 1 9) (4 7 1) (7 3 1))
		((1 2 10) (8 4 7))
		((3 4 7) (3 0 4) (1 2 10))
		((9 2 10) (9 0 2) (8 4 7))
		((2 10 9) (2 9 7) (2 7 3) (7 9 4))
		((8 4 7) (3 11 2))
		((11 4 7) (11 2 4) (2 0 4))
		((9 0 1) (8 4 7) (2 3 11))
		((4 7 11) (9 4 11) (9 11 2) (9 2 1))
		((3 10 1) (3 11 10) (7 8 4))
		((1 11 10) (1 4 11) (1 0 4) (7 11 4))
		((4 7 8) (9 0 11) (9 11 10) (11 0 3))
		((4 7 11) (4 11 9) (9 11 10))
		((9 5 4))
		((9 5 4) (0 8 3))
		((0 5 4) (1 5 0))
		((8 5 4) (8 3 5) (3 1 5))
		((1 2 10) (9 5 4))
		((3 0 8) (1 2 10) (4 9 5))
		((5 2 10) (5 4 2) (4 0 2))
		((2 10 5) (3 2 5) (3 5 4) (3 4 8))
		((9 5 4) (2 3 11))
		((0 11 2) (0 8 11) (4 9 5))
		((0 5 4) (0 1 5) (2 3 11))
		((2 1 5) (2 5 8) (2 8 11) (4 8 5))
		((10 3 11) (10 1 3) (9 5 4))
		((4 9 5) (0 8 1) (8 10 1) (8 11 10))
		((5 4 0) (5 0 11) (5 11 10) (11 0 3))
		((5 4 8) (5 8 10) (10 8 11))
		((9 7 8) (5 7 9))
		((9 3 0) (9 5 3) (5 7 3))
		((0 7 8) (0 1 7) (1 5 7))
		((1 5 3) (3 5 7))
		((9 7 8) (9 5 7) (10 1 2))
		((10 1 2) (9 5 0) (5 3 0) (5 7 3))
		((8 0 2) (8 2 5) (8 5 7) (10 5 2))
		((2 10 5) (2 5 3) (3 5 7))
		((7 9 5) (7 8 9) (3 11 2))
		((9 5 7) (9 7 2) (9 2 0) (2 7 11))
		((2 3 11) (0 1 8) (1 7 8) (1 5 7))
		((11 2 1) (11 1 7) (7 1 5))
		((9 5 8) (8 5 7) (10 1 3) (10 3 11))
		((5 7 0) (5 0 9) (7 11 0) (1 0 10) (11 10 0))
		((11 10 0) (11 0 3) (10 5 0) (8 0 7) (5 7 0))
		((11 10 5) (7 11 5))
		((10 6 5))
		((0 8 3) (5 10 6))
		((9 0 1) (5 10 6))
		((1 8 3) (1 9 8) (5 10 6))
		((1 6 5) (2 6 1))
		((1 6 5) (1 2 6) (3 0 8))
		((9 6 5) (9 0 6) (0 2 6))
		((5 9 8) (5 8 2) (5 2 6) (3 2 8))
		((2 3 11) (10 6 5))
		((11 0 8) (11 2 0) (10 6 5))
		((0 1 9) (2 3 11) (5 10 6))
		((5 10 6) (1 9 2) (9 11 2) (9 8 11))
		((6 3 11) (6 5 3) (5 1 3))
		((0 8 11) (0 11 5) (0 5 1) (5 11 6))
		((3 11 6) (0 3 6) (0 6 5) (0 5 9))
		((6 5 9) (6 9 11) (11 9 8))
		((5 10 6) (4 7 8))
		((4 3 0) (4 7 3) (6 5 10))
		((1 9 0) (5 10 6) (8 4 7))
		((10 6 5) (1 9 7) (1 7 3) (7 9 4))
		((6 1 2) (6 5 1) (4 7 8))
		((1 2 5) (5 2 6) (3 0 4) (3 4 7))
		((8 4 7) (9 0 5) (0 6 5) (0 2 6))
		((7 3 9) (7 9 4) (3 2 9) (5 9 6) (2 6 9))
		((3 11 2) (7 8 4) (10 6 5))
		((5 10 6) (4 7 2) (4 2 0) (2 7 11))
		((0 1 9) (4 7 8) (2 3 11) (5 10 6))
		((9 2 1) (9 11 2) (9 4 11) (7 11 4) (5 10 6))
		((8 4 7) (3 11 5) (3 5 1) (5 11 6))
		((5 1 11) (5 11 6) (1 0 11) (7 11 4) (0 4 11))
		((0 5 9) (0 6 5) (0 3 6) (11 6 3) (8 4 7))
		((6 5 9) (6 9 11) (4 7 9) (7 11 9))
		((10 4 9) (6 4 10))
		((4 10 6) (4 9 10) (0 8 3))
		((10 0 1) (10 6 0) (6 4 0))
		((8 3 1) (8 1 6) (8 6 4) (6 1 10))
		((1 4 9) (1 2 4) (2 6 4))
		((3 0 8) (1 2 9) (2 4 9) (2 6 4))
		((0 2 4) (4 2 6))
		((8 3 2) (8 2 4) (4 2 6))
		((10 4 9) (10 6 4) (11 2 3))
		((0 8 2) (2 8 11) (4 9 10) (4 10 6))
		((3 11 2) (0 1 6) (0 6 4) (6 1 10))
		((6 4 1) (6 1 10) (4 8 1) (2 1 11) (8 11 1))
		((9 6 4) (9 3 6) (9 1 3) (11 6 3))
		((8 11 1) (8 1 0) (11 6 1) (9 1 4) (6 4 1))
		((3 11 6) (3 6 0) (0 6 4))
		((6 4 8) (11 6 8))
		((7 10 6) (7 8 10) (8 9 10))
		((0 7 3) (0 10 7) (0 9 10) (6 7 10))
		((10 6 7) (1 10 7) (1 7 8) (1 8 0))
		((10 6 7) (10 7 1) (1 7 3))
		((1 2 6) (1 6 8) (1 8 9) (8 6 7))
		((2 6 9) (2 9 1) (6 7 9) (0 9 3) (7 3 9))
		((7 8 0) (7 0 6) (6 0 2))
		((7 3 2) (6 7 2))
		((2 3 11) (10 6 8) (10 8 9) (8 6 7))
		((2 0 7) (2 7 11) (0 9 7) (6 7 10) (9 10 7))
		((1 8 0) (1 7 8) (1 10 7) (6 7 10) (2 3 11))
		((11 2 1) (11 1 7) (10 6 1) (6 7 1))
		((8 9 6) (8 6 7) (9 1 6) (11 6 3) (1 3 6))
		((0 9 1) (11 6 7))
		((7 8 0) (7 0 6) (3 11 0) (11 6 0))
		((7 11 6))
		((7 6 11))
		((3 0 8) (11 7 6))
		((0 1 9) (11 7 6))
		((8 1 9) (8 3 1) (11 7 6))
		((10 1 2) (6 11 7))
		((1 2 10) (3 0 8) (6 11 7))
		((2 9 0) (2 10 9) (6 11 7))
		((6 11 7) (2 10 3) (10 8 3) (10 9 8))
		((7 2 3) (6 2 7))
		((7 0 8) (7 6 0) (6 2 0))
		((2 7 6) (2 3 7) (0 1 9))
		((1 6 2) (1 8 6) (1 9 8) (8 7 6))
		((10 7 6) (10 1 7) (1 3 7))
		((10 7 6) (1 7 10) (1 8 7) (1 0 8))
		((0 3 7) (0 7 10) (0 10 9) (6 10 7))
		((7 6 10) (7 10 8) (8 10 9))
		((6 8 4) (11 8 6))
		((3 6 11) (3 0 6) (0 4 6))
		((8 6 11) (8 4 6) (9 0 1))
		((9 4 6) (9 6 3) (9 3 1) (11 3 6))
		((6 8 4) (6 11 8) (2 10 1))
		((1 2 10) (3 0 11) (0 6 11) (0 4 6))
		((4 11 8) (4 6 11) (0 2 9) (2 10 9))
		((10 9 3) (10 3 2) (9 4 3) (11 3 6) (4 6 3))
		((8 2 3) (8 4 2) (4 6 2))
		((0 4 2) (4 6 2))
		((1 9 0) (2 3 4) (2 4 6) (4 3 8))
		((1 9 4) (1 4 2) (2 4 6))
		((8 1 3) (8 6 1) (8 4 6) (6 10 1))
		((10 1 0) (10 0 6) (6 0 4))
		((4 6 3) (4 3 8) (6 10 3) (0 3 9) (10 9 3))
		((10 9 4) (6 10 4))
		((4 9 5) (7 6 11))
		((0 8 3) (4 9 5) (11 7 6))
		((5 0 1) (5 4 0) (7 6 11))
		((11 7 6) (8 3 4) (3 5 4) (3 1 5))
		((9 5 4) (10 1 2) (7 6 11))
		((6 11 7) (1 2 10) (0 8 3) (4 9 5))
		((7 6 11) (5 4 10) (4 2 10) (4 0 2))
		((3 4 8) (3 5 4) (3 2 5) (10 5 2) (11 7 6))
		((7 2 3) (7 6 2) (5 4 9))
		((9 5 4) (0 8 6) (0 6 2) (6 8 7))
		((3 6 2) (3 7 6) (1 5 0) (5 4 0))
		((6 2 8) (6 8 7) (2 1 8) (4 8 5) (1 5 8))
		((9 5 4) (10 1 6) (1 7 6) (1 3 7))
		((1 6 10) (1 7 6) (1 0 7) (8 7 0) (9 5 4))
		((4 0 10) (4 10 5) (0 3 10) (6 10 7) (3 7 10))
		((7 6 10) (7 10 8) (5 4 10) (4 8 10))
		((6 9 5) (6 11 9) (11 8 9))
		((3 6 11) (0 6 3) (0 5 6) (0 9 5))
		((0 11 8) (0 5 11) (0 1 5) (5 6 11))
		((6 11 3) (6 3 5) (5 3 1))
		((1 2 10) (9 5 11) (9 11 8) (11 5 6))
		((0 11 3) (0 6 11) (0 9 6) (5 6 9) (1 2 10))
		((11 8 5) (11 5 6) (8 0 5) (10 5 2) (0 2 5))
		((6 11 3) (6 3 5) (2 10 3) (10 5 3))
		((5 8 9) (5 2 8) (5 6 2) (3 8 2))
		((9 5 6) (9 6 0) (0 6 2))
		((1 5 8) (1 8 0) (5 6 8) (3 8 2) (6 2 8))
		((1 5 6) (2 1 6))
		((1 3 6) (1 6 10) (3 8 6) (5 6 9) (8 9 6))
		((10 1 0) (10 0 6) (9 5 0) (5 6 0))
		((0 3 8) (5 6 10))
		((10 5 6))
		((11 5 10) (7 5 11))
		((11 5 10) (11 7 5) (8 3 0))
		((5 11 7) (5 10 11) (1 9 0))
		((10 7 5) (10 11 7) (9 8 1) (8 3 1))
		((11 1 2) (11 7 1) (7 5 1))
		((0 8 3) (1 2 7) (1 7 5) (7 2 11))
		((9 7 5) (9 2 7) (9 0 2) (2 11 7))
		((7 5 2) (7 2 11) (5 9 2) (3 2 8) (9 8 2))
		((2 5 10) (2 3 5) (3 7 5))
		((8 2 0) (8 5 2) (8 7 5) (10 2 5))
		((9 0 1) (5 10 3) (5 3 7) (3 10 2))
		((9 8 2) (9 2 1) (8 7 2) (10 2 5) (7 5 2))
		((1 3 5) (3 7 5))
		((0 8 7) (0 7 1) (1 7 5))
		((9 0 3) (9 3 5) (5 3 7))
		((9 8 7) (5 9 7))
		((5 8 4) (5 10 8) (10 11 8))
		((5 0 4) (5 11 0) (5 10 11) (11 3 0))
		((0 1 9) (8 4 10) (8 10 11) (10 4 5))
		((10 11 4) (10 4 5) (11 3 4) (9 4 1) (3 1 4))
		((2 5 1) (2 8 5) (2 11 8) (4 5 8))
		((0 4 11) (0 11 3) (4 5 11) (2 11 1) (5 1 11))
		((0 2 5) (0 5 9) (2 11 5) (4 5 8) (11 8 5))
		((9 4 5) (2 11 3))
		((2 5 10) (3 5 2) (3 4 5) (3 8 4))
		((5 10 2) (5 2 4) (4 2 0))
		((3 10 2) (3 5 10) (3 8 5) (4 5 8) (0 1 9))
		((5 10 2) (5 2 4) (1 9 2) (9 4 2))
		((8 4 5) (8 5 3) (3 5 1))
		((0 4 5) (1 0 5))
		((8 4 5) (8 5 3) (9 0 5) (0 3 5))
		((9 4 5))
		((4 11 7) (4 9 11) (9 10 11))
		((0 8 3) (4 9 7) (9 11 7) (9 10 11))
		((1 10 11) (1 11 4) (1 4 0) (7 4 11))
		((3 1 4) (3 4 8) (1 10 4) (7 4 11) (10 11 4))
		((4 11 7) (9 11 4) (9 2 11) (9 1 2))
		((9 7 4) (9 11 7) (9 1 11) (2 11 1) (0 8 3))
		((11 7 4) (11 4 2) (2 4 0))
		((11 7 4) (11 4 2) (8 3 4) (3 2 4))
		((2 9 10) (2 7 9) (2 3 7) (7 4 9))
		((9 10 7) (9 7 4) (10 2 7) (8 7 0) (2 0 7))
		((3 7 10) (3 10 2) (7 4 10) (1 10 0) (4 0 10))
		((1 10 2) (8 7 4))
		((4 9 1) (4 1 7) (7 1 3))
		((4 9 1) (4 1 7) (0 8 1) (8 7 1))
		((4 0 3) (7 4 3))
		((4 8 7))
		((9 10 8) (10 11 8))
		((3 0 9) (3 9 11) (11 9 10))
		((0 1 10) (0 10 8) (8 10 11))
		((3 1 10) (11 3 10))
		((1 2 11) (1 11 9) (9 11 8))
		((3 0 9) (3 9 11) (1 2 9) (2 11 9))
		((0 2 11) (8 0 11))
		((3 2 11))
		((2 3 8) (2 8 10) (10 8 9))
		((9 10 2) (0 9 2))
		((2 3 8) (2 8 10) (0 1 8) (1 10 8))
		((1 10 2))
		((1 3 8) (9 1 8))
		((0 9 1))
		((0 3 8))
		(())))

;linearly interpolate the position where an isosurface cuts
;an edge between two vertices, each with their own scalar value

(defun vertex-interp (isolevel p1 p2 valp1 valp2)
	; (vertex-interp isolevel p1 p2 valp1 valp2) -> p
	(cond
		((< (abs (- isolevel valp1)) (const (n2r 0.0001))) p1)
		((< (abs (- isolevel valp2)) (const (n2r 0.0001))) p2)
		((< (abs (- valp1 valp2)) (const (n2r 0.0001))) p1)
		(:t (vec-add p1 (vec-scale (vec-sub p2 p1 +reals_tmp3)
				(/ (- isolevel valp1) (- valp2 valp1)) +reals_tmp3)))))

;given a grid cell and an isolevel, calculate the triangular
;facets required to represent the isosurface through the cell.
;return the list of triangular facets, at most 5 triangular facets.
;an empty list will be returned if the grid cell is either totally above
;or totally below the isolevel.

(defun iso-surface (grid isolevel)
	; (iso-surface grid isolevel) -> tris
	;determine the index into the edge table which
	;tells us which vertices are inside the surface
	(defq cubeindex (reduce (lambda (cubeindex (b v))
				(+ cubeindex (if (<= (elem-get grid v) isolevel) b 0)))
			(static-q (
			(1 +gridcell_v0) (2 +gridcell_v1)
			(4 +gridcell_v2) (8 +gridcell_v3)
			(16 +gridcell_v4) (32 +gridcell_v5)
			(64 +gridcell_v6) (128 +gridcell_v7))) 0))
	(cond
		((= (defq cube (elem-get +edge_table cubeindex)) 0)
			;cube is entirely in/out of the surface
			'())
		(:t ;find the vertices where the surface intersects the cube
			(defq vertlist (reduce (lambda (vertlist (i p0 p1 v0 v1))
						(push vertlist (if (= (logand cube i) 0) :nil
							(vertex-interp isolevel
								(elem-get grid p0) (elem-get grid p1)
								(elem-get grid v0) (elem-get grid v1)))))
					(static-q (
					(1 +gridcell_p0 +gridcell_p1 +gridcell_v0 +gridcell_v1)
					(2 +gridcell_p1 +gridcell_p2 +gridcell_v1 +gridcell_v2)
					(4 +gridcell_p2 +gridcell_p3 +gridcell_v2 +gridcell_v3)
					(8 +gridcell_p3 +gridcell_p0 +gridcell_v3 +gridcell_v0)
					(16 +gridcell_p4 +gridcell_p5 +gridcell_v4 +gridcell_v5)
					(32 +gridcell_p5 +gridcell_p6 +gridcell_v5 +gridcell_v6)
					(64 +gridcell_p6 +gridcell_p7 +gridcell_v6 +gridcell_v7)
					(128 +gridcell_p7 +gridcell_p4 +gridcell_v7 +gridcell_v4)
					(256 +gridcell_p0 +gridcell_p4 +gridcell_v0 +gridcell_v4)
					(512 +gridcell_p1 +gridcell_p5 +gridcell_v1 +gridcell_v5)
					(1024 +gridcell_p2 +gridcell_p6 +gridcell_v2 +gridcell_v6)
					(2048 +gridcell_p3 +gridcell_p7 +gridcell_v3 +gridcell_v7))) (list)))
			;return the triangles
			(map (lambda ((p0 p1 p2))
					(list (elem-get vertlist p0) (elem-get vertlist p1) (elem-get vertlist p2)))
				(elem-get +tri_table cubeindex)))))

(defclass Iso (width height depth) :nil
	; (Iso) -> iso
	(def this :width width :height height :depth depth
		:center (vec-scale (Vec3-r (n2r (dec width)) (n2r (dec height)) (n2r (dec depth))) +real_1/2)
		:scale (vec-div (Vec3-r +real_2 +real_2 +real_2) (Vec3-r (n2r width) (n2r height) (n2r depth))))

	(defabstractmethod :get_scalar (this x y z))
		; (. iso :get_scalar x y z) -> scalar

	(defmethod :get_metrics ()
		; (. iso :get_metrics) -> (width height depth)
		(list (get :width this) (get :height this) (get :depth this)))

	(defmethod :get_gridcell (x y z)
		; (. iso :get_gridcell x y z) -> gridcell
		(raise :width :height :depth :center :scale)
		(defq ix (inc x) iy (inc y) iz (inc z)
			rx (n2r x) ry (n2r y) rz (n2r z) rix (n2r ix) riy (n2r iy) riz (n2r iz)
			get_scalar_fnc (.? this :get_scalar))
		(Gridcell
			(vec-mul scale (vec-sub (Vec3-r rx ry riz) center +reals_tmp3))
			(vec-mul scale (vec-sub (Vec3-r rix ry riz) center +reals_tmp3))
			(vec-mul scale (vec-sub (Vec3-r rix ry rz) center +reals_tmp3))
			(vec-mul scale (vec-sub (Vec3-r rx ry rz) center +reals_tmp3))
			(vec-mul scale (vec-sub (Vec3-r rx riy riz) center +reals_tmp3))
			(vec-mul scale (vec-sub (Vec3-r rix riy riz) center +reals_tmp3))
			(vec-mul scale (vec-sub (Vec3-r rix riy rz) center +reals_tmp3))
			(vec-mul scale (vec-sub (Vec3-r rx riy rz) center +reals_tmp3))
			(get_scalar_fnc this x y iz)
			(get_scalar_fnc this ix y iz)
			(get_scalar_fnc this ix y z)
			(get_scalar_fnc this x y z)
			(get_scalar_fnc this x iy iz)
			(get_scalar_fnc this ix iy iz)
			(get_scalar_fnc this ix iy z)
			(get_scalar_fnc this x iy z)))

	(defmethod :get_surface (x y z isolevel)
		; (. iso :get_surface x y z isolevel) -> triangles
		(iso-surface (. this :get_gridcell x y z) isolevel))
	)

(defclass Iso-sphere (width height depth) (Iso width height depth)
	; (Iso-sphere width height depth) -> iso

	(defmethod :get_scalar (x y z)
		; (. iso :get_scalar x y z) -> scalar
		(raise :center :scale)
		(vec-length (vec-mul (vec-sub
			(Vec3-r (n2r x) (n2r y) (n2r z)) center +reals_tmp3) scale +reals_tmp3)))
	)

(defclass Iso-cube (width height depth) (Iso width height depth)
	; (Iso-cube width height depth) -> iso

	(defmethod :get_scalar (x y z)
		; (. iso :get_scalar x y z) -> scalar
		(raise :center :scale)
		(reduce max (vec-abs (vec-mul (vec-sub
			(Vec3-r (n2r x) (n2r y) (n2r z)) center +reals_tmp3) scale +reals_tmp3) +reals_tmp3)))
	)

(defclass Iso-tetra (width height depth) (Iso width height depth)
	; (Iso-tetra width height depth) -> iso

	(defmethod :get_scalar (x y z)
		; (. iso :get_scalar x y z) -> scalar
		(raise :center :scale)
		(vec-sum (vec-abs (vec-mul (vec-sub
			(Vec3-r (n2r x) (n2r y) (n2r z)) center +reals_tmp3) scale +reals_tmp3) +reals_tmp3)))
	)

(defclass Iso-capsule (width height depth) (Iso width height depth)
	; (Iso-capsule width height depth) -> iso

	(defmethod :get_scalar (x y z)
		; (. iso :get_scalar x y z) -> scalar
		(raise :center :scale)
		(vec-dist-to-line (vec-mul (vec-sub
			(Vec3-r (n2r x) (n2r y) (n2r z)) center +reals_tmp3) scale +reals_tmp3)
			(const (Vec3-r (n2r -0.5) (n2r 0.0) (n2r 0.0)))
			(const (Vec3-r (n2r 0.5) (n2r 0.0) (n2r 0.0)))))
	)

;module
(export-classes '(Iso Iso-sphere Iso-tetra Iso-capsule Iso-cube))
(env-pop)
